/*
*	Copyright (C) 2014  Julio Montes, Mario Carrillo
*
*	Julio Montes e-mail: imc.coder@gmail.com
*
*	Mario Carrillo e-mail: mario_90ago@live.com.mx
*
*	BSD 3-Clause License
*/

#include "alliance/include/tool.h"

#include <wx/tokenzr.h>

namespace alliance
{
    /*const wxString Tool::s_typeInput = _T( "isinput" );
    const wxString Tool::s_typeOutput = _T( "isoutput" );
    const wxString Tool::s_typePattern = _T( "ispattern" );*/

    Tool::Tool( const wxString &command, const wxString &commandFormat )
        : m_command( command )
        , m_commandFormat( commandFormat )
    {

    }

    Tool::~Tool()
    {

    }

    const wxString &Tool::GetName() const
    {
        return m_command;
    }

    void Tool::Save( sdk::FileConfig *fileConfig )
    {
        const size_t position = fileConfig->WriteNewString( _T( "/alliance/tools/tool" ), m_command );
        fileConfig->WriteString( _T( "/alliance/tools/tool" ), m_commandFormat, _T( "format" ), position );

        fileConfig->WriteNewElements( _T( "/alliance/tools/tool" ), position, m_options );

        fileConfig->WriteNewElements( _T( "/alliance/tools/tool" ), position, m_variables );

        fileConfig->WriteNewElements( _T( "/alliance/tools/tool" ), position, m_others );

    }

    bool Tool::Load( const sdk::multimapElements &elements )
    {
        for( sdk::multimapElements::const_iterator it = elements.begin(); it != elements.end(); ++it )
        {
            if( 0 == it->first.CmpNoCase( _T( "option" ) ) )
            {
                AddOption( it->second.m_mapAttributes );
            }
            else if( 0 == it->first.CmpNoCase( _T( "variable" ) ) )
            {
                AddVariable( it->second.m_mapAttributes );
            }
            else //other
            {
                AddOther( it->first, it->second.m_mapAttributes );
            }
        }

        return true;
    }

    void Tool::AddOption( const sdk::mapAttributes &attributes )
    {
        wxString value;
        wxString additional;

        attributes.Get( _T( "value" ), &value );
        attributes.Get( _T( "additional" ), &additional );

        AddOption( value, additional );
    }

    void Tool::AddVariable( const sdk::mapAttributes &attributes )
    {
        wxString name;
        wxString value;

        attributes.Get( _T( "name" ), &name );
        attributes.Get( _T( "value" ), &value );

        AddVariable( name, value );
    }

    void Tool::AddOther( const wxString &name, const sdk::mapAttributes &attributes )
    {
        wxString value;

        attributes.Get( _T( "value" ), &value );

        /*else if( 0 == l_name.CmpNoCase( _T( "type" ) ) )//TODO: change type by other name
        {
            type = l_value;
        }*/

        AddOther( name, value, _T( "" ) );//TODO:
    }

    wxString Tool::GetCommandForFile() const
    {
        wxString command;

        wxString variableName;
        wxString variableValue;
        for( sdk::multimapSimpleElements::const_iterator it = m_variables.begin(); it != m_variables.end(); ++it )
        {
            it->second.Get( _T( "name" ), &variableName );
            it->second.Get( _T( "value" ), &variableValue);
            command += _T( "export " ) + variableName + _T( "=" ) + variableValue + _T( "\n" );
        }

        wxStringTokenizer st( m_commandFormat, wxT( " \n\t\r" ), wxTOKEN_STRTOK );
        while( st.HasMoreTokens() )
        {
            const wxString &token = st.GetNextToken();
            if( 0 == token.CmpNoCase( _T( "command" ) ) )
            {
                command += m_command + _T( " " );
            }
            else if( 0 == token.CmpNoCase( _T( "options" ) ) )
            {
                for( sdk::multimapSimpleElements::const_iterator it = m_options.begin(); it != m_options.end(); ++it )
                {
                    wxString option;
                    wxString additional;
                    it->second.Get( _T( "value" ), &option );
                    it->second.Get( _T( "additional" ), &additional );

                    command += option;

                    if( option.EndsWith( _T( "=" ) ) )//TODO: maybe modify in XML
                    {
                        command += additional;
                    }
                    else if( !additional.IsEmpty() )
                    {
                        command += _T( " " ) + additional;
                    }

                    command += _T( " " );
                }
            }
            else
            {
                for( sdk::multimapSimpleElements::const_iterator it = m_others.begin(); it != m_others.end(); ++it )
                {
                    if( it->first == token )
                    {
                        /*const sdk::vectorAttributesString &vAttributes = m_vectorOthers[i].vectorAttributes; //TODO: modify in file.tool
                        bool hasType = false;
                        wxString value;
                        for( size_t j=0; j<vAttributes.size(); ++j )
                        {
                            if( 0 == vAttributes[j].name.Cmp( _T( "value" ) ) )
                            {
                                value = vAttributes[j].value;
                            }
                            else if( 0 == vAttributes[j].name.Cmp( _T( "type" ) ) &&
                                ( 0 == vAttributes[j].value.Cmp( s_typeOutput ) ||
                                  0 == vAttributes[j].value.Cmp( s_typeInput )  ||
                                  0 == vAttributes[j].value.Cmp( s_typePattern ) ) )
                            {
                                hasType = true;
                            }
                        }

                        if( hasType && value.Find( _T( '.' ) ) != wxNOT_FOUND )
                        {
                            value = value.BeforeLast( _T( '.' ) );
                        }

                        command += value + _T( " " );*/
                    }
                }
            }
        }

        return command;
    }

    //TODO: remove
    /*wxString Tool::GetFileByType( const wxString &type ) const
    {
        wxString value;
        bool found = false;
        for( size_t i=0; i<m_vectorOthers.size() && !found; ++i )
        {
            const sdk::vectorAttributesString &vAttributes = m_vectorOthers[i].vectorAttributes;
            for( size_t j=0; j<vAttributes.size(); ++j )
            {
                if( 0 == vAttributes[j].name.Cmp( _T( "value" ) ) )
                {
                    value = vAttributes[j].value;
                }
                if( 0 == vAttributes[j].name.Cmp( _T( "type" ) ) &&
                    0 == vAttributes[j].value.Cmp( type ) )
                {
                    found = true;
                }
            }
        }

        return value;
    }*/

    void Tool::AddVariable( const wxString &name, const wxString &value )
    {
        //TODO: check
        sdk::mapAttributes &attribute = ( m_variables.insert( std::pair<sdk::multimapSimpleElements::key_type, sdk::multimapSimpleElements::mapped_type>( _T( "variable" ), sdk::mapAttributes() ) )->second );

        attribute[ _T( "name" ) ] = name;

        attribute[ _T( "value" ) ] = value;
    }

    void Tool::AddOption( const wxString &value, const wxString &additional  )
    {
        //TODO: check
        sdk::mapAttributes &attribute = ( m_options.insert( std::pair<sdk::multimapSimpleElements::key_type, sdk::multimapSimpleElements::mapped_type>( _T( "option" ), sdk::mapAttributes() ) )->second );

        attribute[ _T( "value" ) ] = value;

        if( !additional.IsEmpty() )
        {
            attribute[ _T( "additional" ) ] = additional;
        }

    }

    void Tool::AddOther( const wxString &name, const wxString &value, const wxString &type )//TODO: remove use of attribute type
    {
        sdk::mapAttributes &attribute = ( m_options.insert( std::pair<sdk::multimapSimpleElements::key_type, sdk::multimapSimpleElements::mapped_type>( name, sdk::mapAttributes() ) )->second );

        attribute[ _T( "value" ) ] = value;

        /*if( !type.IsEmpty() ) //TODO:
        {
            attribute.name = _T( "type" );
            attribute.value = type;
            element.vectorAttributes.push_back( attribute );
        }*/
    }

    /*const vectorVariables &Tool::GetVariables() const
    {
        return m_vectorVariables;
    }

    const vectorOptions &Tool::GetOptions() const
    {
        return m_vectorOptions;
    }

    const vectorOthers &Tool::GetOthers() const
    {
        return m_vectorOthers;
    }*/
}
